﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Windows.Forms;

using TLL.Finance.Currencys;
using TLL.Finance;
using TLL.UTL;
using TLL.Debug;

namespace TLL.Finance.BankSys
{
    public class PrivateAPI
    {
        private string paymentID = string.Empty;
        private List<BankMerchant> merchants = new List<BankMerchant>();
        private Error error = null;
        private Warning warning = null;
        private NotifyIcon notify = null;

        public PrivateAPI(string paymentID, List<BankMerchant> merchants)
        {
            this.paymentID = paymentID;
            this.merchants = merchants;
        }
        public PrivateAPI(string paymentID, List<BankMerchant> merchants, NotifyIcon notify)
        {
            this.paymentID = paymentID;
            this.merchants = merchants;
            this.notify = notify;
        }


        public List<BankCard> GeBalances()
        {
            try
            {
                var res = new List<BankCard>();
                foreach (var merchant in this.merchants)
                {
                    var data = @"<oper>cmt</oper><wait>0</wait><test>1</test><payment id='" + this.paymentID + "'><prop name='cardnum' value='" + merchant.Card + "' /><prop name='country' value='UA' /></payment>";

                    var str = string.Empty;
                    str += @"<request version='1.0'><merchant><id>" + merchant.ID.ToString() + "</id><signature>" + Utilities.GetSHA1(Utilities.MD5Hash(data + merchant.Password)).Replace("-", "").ToLower() + @"</signature></merchant><data><oper>cmt</oper><wait>0</wait><test>1</test><payment id='" + this.paymentID + "'><prop name='cardnum' value='" + merchant.Card + "' /><prop name='country' value='UA' /></payment></data></request>";
                    XmlDocument document = new XmlDocument();

                    var unsverRequest = Utilities.SendXMLRequest("https://api.privatbank.ua/p24api/balance", str);
                    document.LoadXml(unsverRequest);

                    res.Add(new BankCard(
                        FindNode(document.ChildNodes[1], "acc_name").InnerText,
                        FindNode(document.ChildNodes[1], "card_number").InnerText,
                        Utilities.GetEnum<CurrencyType>(FindNode(document.ChildNodes[1], "currency").InnerText),
                        double.Parse(FindNode(document.ChildNodes[1], "balance").InnerText.Replace('.', ','))
                        ));
                }
                return res;
            }
            catch 
            {
                this.error = new Error(ErrorType.Get);
                this.warning = new Warning(
                    WarningType.PrivateAPI,
                    string.Format("Error getting balance"),
                    this.notify,
                    delegate(object sender, EventArgs e) {
                        this.error.Show(DisplayDebugType.MessageBox);
                    });
                if (this.notify != null)
                    this.warning.Show(DisplayDebugType.Notify);
                else
                    this.error.Show(DisplayDebugType.MessageBox);
            }
            return null;
        }
        public List<BankInvoice> GetAccountStatements()
        {
            try
            {
                var res = new List<BankInvoice>();

                foreach (var merchant in this.merchants)
                {
                    var data = @"<oper>cmt</oper><wait>0</wait><test>1</test><payment id='" + this.paymentID + "'><prop name='sd' value='01.01.2013' /><prop name='ed' value='" + DateTime.Now.ToShortDateString() + "' /><prop name='card' value='" + merchant.Card + "' /></payment>";

                    var str = string.Empty;
                    str += @"<request version='1.0'><merchant><id>" + merchant.ID.ToString() + "</id><signature>" + Utilities.GetSHA1(Utilities.MD5Hash(data + merchant.Password)).Replace("-", "").ToLower() + @"</signature></merchant><data><oper>cmt</oper><wait>0</wait><test>1</test><payment id='" + this.paymentID + "'><prop name='sd' value='01.01.2013' /><prop name='ed' value='" + DateTime.Now.ToShortDateString() + "' /><prop name='card' value='" + merchant.Card + "' /></payment></data></request>";
                    XmlDocument document = new XmlDocument();

                    var unsverRequest = Utilities.SendXMLRequest("https://api.privatbank.ua/p24api/rest_fiz", str);
                    document.LoadXml(unsverRequest);

                    var info = FindNode(document.ChildNodes[1], "statements");

                    foreach (XmlNode node in info.ChildNodes)
                        res.Add(new BankInvoice(
                            FindAttribute(node, "card").Value,
                            DateTime.Parse(FindAttribute(node, "trandate").Value),
                            double.Parse(FindAttribute(node, "amount").Value.Replace('.', ',').Split(' ')[0]),
                            double.Parse(FindAttribute(node, "rest").Value.Replace('.', ',').Split(' ')[0]),
                            FindAttribute(node, "terminal").Value,
                            double.Parse(FindAttribute(node, "cardamount").Value.Replace('.', ',').Split(' ')[0]) > 0,
                            Utilities.GetEnum<CurrencyType>(FindAttribute(node, "amount").Value.Replace('.', ',').Split(' ')[1])
                            ));
                }
                return res;
            }
            catch 
            {
                this.error = new Error(ErrorType.Get);
                this.warning = new Warning(
                    WarningType.PrivateAPI,
                    string.Format("Error getting account statements"),
                    this.notify,
                    delegate(object sender, EventArgs e) {
                        this.error.Show(DisplayDebugType.MessageBox);
                    });
                if (this.notify != null)
                    this.warning.Show(DisplayDebugType.Notify);
                else
                    this.error.Show(DisplayDebugType.MessageBox);
            }
            return null;
        }
        private XmlNode FindNode(XmlNode node, string name)
        {
            foreach (XmlNode childNode in node)
                if (childNode.Name == name)
                {
                    return childNode;
                }
                else if (childNode.ChildNodes.Count != 0)
                {
                    var findNode = FindNode(childNode, name);
                    if (findNode != null)
                        return findNode;
                }
            return null;

        }
        private XmlAttribute FindAttribute(XmlNode node, string name)
        {
            foreach (XmlAttribute attribute in node.Attributes)
                if (attribute.Name == name)
                    return attribute;
            return null;
        }
    }
}
